/** proc.c: Implementation of `process' syscalls
 *
 * Author: 	Nora Tarano <ntarano@andrew.cmu.edu>
 *          Yuan Meng <yuanm@andrew.cmu.edu>
 *          Yipeng Yun <yipengy@andrew.cmu.edu>
 * Date: 	Dec 11, 2011
 */

#include <types.h>
#include <exports.h>
#include <config.h>
#include <kernel.h>
#include <sched.h>
#include <device.h>

#include <bits/errno.h>

#include <arm/reg.h>
#include <arm/psr.h>
#include <arm/exception.h>
#include <arm/physmem.h>

extern const unsigned long dev_freq[NUM_DEVICES]; 

int task_create(task_t* tasks, size_t num_tasks)
{
	task_t* task_list[OS_MAX_TASKS];

	if(num_tasks > OS_MAX_TASKS - 2)
		return -EINVAL;
		
	if(!valid_addr(tasks, sizeof(task_t)*num_tasks, USR_START_ADDR, USR_END_ADDR))
	    return -EFAULT;

	unsigned int i;
	for(i=0; i < num_tasks; i++)
		task_list[i] = &tasks[i];

	disable_interrupts();
	allocate_tasks(task_list, num_tasks);
	dispatch_nosave();

	return 0;
}

int event_wait(unsigned int dev)
{
	tcb_t *task = get_cur_tcb();

	if (dev >= NUM_DEVICES) 
		return -EINVAL;
	else if (task->holds_lock)	// check if the task is locked
		return -EHOLDSLOCK;
	else
	{
		disable_interrupts();
		dev_wait(dev);
		enable_interrupts();
		return 0;
	}
}

/* An invalid syscall causes the kernel to exit. */
void invalid_syscall(unsigned int call_num)
{
	printf("Kernel panic: invalid syscall -- 0x%08x\n", call_num);

	disable_interrupts();
	while(1);
}
